/************************************************************

  This example shows how to write data and read it from a dataset
  using bzip2 compression. 
  bzip2 filter is not available in HDF5. 
  The example uses a new feature available in HDF5 version 1.8.11 
  to discover, load and register filters at run time.  

 ************************************************************/

#include "hdf5.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define FILENAME            "h5ex_d_bzip23.h5"
#define DATASET         "DS1"
#define DIM1            3200
#define DIM2            6400
#define DIM0            1
#define CHUNK1          3200
#define CHUNK2          6400
#define CHUNK0          1
#define H5Z_FILTER_JXR        307
#define QUALITY			255

int
main (void)
{


    hid_t           file, space, dset, dcpl;  
    herr_t          status;
    H5Z_filter_t    filter_id = 0;
    char            filter_name[80];

    hsize_t         dims[3] = {DIM0, DIM1, DIM2},
                    chunk[3] = {CHUNK0, CHUNK1, CHUNK2};
    size_t          nelmts = 3; 

    const unsigned int cd_values[3] = {CHUNK1,CHUNK2,QUALITY};   
    unsigned int       values_out[1] = {99};        
    unsigned int    flags;
    htri_t          avail;
    unsigned        filter_config;

	uint16_t i,j,k,max;
	uint16_t ***wdata;
	uint16_t ***rdata;
	uint16_t fill_value = 1;
	wdata = malloc(DIM0 * sizeof(int *));
	rdata = malloc(DIM0 * sizeof(int *));
	for(i = 0; i < DIM0; i++){
		wdata[i] = malloc(DIM1 * sizeof(int));
		rdata[i] = malloc(DIM1 * sizeof(int));
		for(j = 0; j < DIM2; j++){
			wdata[i][j] = malloc(DIM2 * sizeof(int));
			rdata[i][j] = malloc(DIM2 * sizeof(int));
		}
	}
/*	for (i=0; i<DIM0; i++){*/
/*		uint16_t* wdata[i] = malloc(DIM1*sizeof(uint16_t));*/
/*		for (j=0; j<DIM1; j++)*/
/*			uint16_t* wdata[i][j] = malloc(DIM2*sizeof(uint16_t));*/
/*	}*/
    //uint16_t        wdata[DIM0][DIM1][DIM2];
          
    //uint16_t        rdata[DIM0][DIM1][DIM2]; 
    
    for (i=0; i<DIM0; i++)
        for (j=0; j<DIM1; j++)
			for (k=0; k<DIM2; k++)
            	wdata[i][j][k] = fill_value;

    FILE* file_ptr2;
    file_ptr2 = fopen("before.raw", "wb");
    fwrite(wdata, 1, DIM0*DIM1*2, file_ptr2);
    fclose(file_ptr2);

    file = H5Fcreate (FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    space = H5Screate_simple (3, dims, NULL);

    dcpl = H5Pcreate (H5P_DATASET_CREATE);
    status = H5Pset_filter (dcpl, H5Z_FILTER_JXR, H5Z_FLAG_MANDATORY, (size_t)nelmts, cd_values);

     avail = H5Zfilter_avail(H5Z_FILTER_JXR);
    if (avail) {
        status = H5Zget_filter_info (H5Z_FILTER_JXR, &filter_config);
        if ( (filter_config & H5Z_FILTER_CONFIG_ENCODE_ENABLED) && 
                (filter_config & H5Z_FILTER_CONFIG_DECODE_ENABLED) ) 
            printf ("bzip2 filter is available for encoding and decoding.\n");
    }     
    status = H5Pset_chunk (dcpl, 3, chunk);

    printf ("....Writing bzip2 compressed data ................\n");
    dset = H5Dcreate (file, DATASET, H5T_STD_U16BE, space, H5P_DEFAULT, dcpl,
                H5P_DEFAULT);

    status = H5Dwrite (dset, H5T_NATIVE_USHORT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
                wdata[0]); //segfault
    status = H5Pclose (dcpl);
    status = H5Dclose (dset);
    status = H5Sclose (space);
    status = H5Fclose (file);
    status = H5close();


    printf ("....Close the file and reopen for reading ........\n");
    file = H5Fopen (FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
    dset = H5Dopen (file, DATASET, H5P_DEFAULT);

    dcpl = H5Dget_create_plist (dset);

    filter_id = H5Pget_filter2 (dcpl, (unsigned) 0, &flags, &nelmts, values_out, sizeof(filter_name), filter_name, NULL);
    printf ("Filter info is available from the dataset creation property \n ");
    printf ("  Filter identifier is ");
    switch (filter_id) {
        case H5Z_FILTER_JXR:
            printf ("%d\n", filter_id);
            printf ("   Number of parameters is %d with the value %u\n", nelmts, values_out[0]);
            printf ("   To find more about the filter check %s\n", filter_name);
            break;
        default:
            printf ("Not expected filter\n");
            break;
    }
     avail = H5Zfilter_avail(H5Z_FILTER_JXR);
    if (!avail) 
        printf ("bzip2 filter is not yet available after the H5Pget_filter call.\n");
    else
		return 1;
    
    printf ("....Reading bzip2 compressed data ................\n");

    status = H5Dread (dset, H5T_NATIVE_USHORT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
                rdata[0]);

    FILE* file_ptr;
    file_ptr = fopen("after.raw", "wb");
    fwrite(rdata, 1, DIM0*DIM1*2, file_ptr);
    fclose(file_ptr); 

	printf ("################ test status %d\n",status);

    max = rdata[0][0];
    for (i=0; i<DIM0; i++)
        for (j=0; j<DIM1; j++) {
            if (max < rdata[i][j])
                max = rdata[i][j];
        }
    printf ("Maximum value in %s is %d\n", DATASET, max);
    avail = H5Zfilter_avail(H5Z_FILTER_JXR);
    if (avail)  
        printf ("bzip2 filter is available now since H5Dread triggered loading of the filter.\n");

    status = H5Pclose (dcpl);
    status = H5Dclose (dset);
    status = H5Fclose (file);

    return 0;
}
